#include "nr_device.h"

nr_device::nr_device()
    : m_status(NR_DEVICE_STATUS_STOPPED)
    , m_delegate(NULL)
    , m_parent_device(NULL)
    , m_device_item(NULL)
{
}

nr_device::~nr_device()
{
}

nr_error_t nr_device::start() 
{ 
    // Try to start its parent first
    if (m_parent_device != NULL)
    {
        nr_error_t status = m_parent_device->start();
        if (NR_FAILED(status))
            return status;
    }

    m_status = NR_DEVICE_STATUS_STARTED;
    return NR_ERROR_NONE; 
}

nr_error_t nr_device::stop() 
{ 
    // Try to stop all its' child
    m_status = NR_DEVICE_STATUS_STOPPED;
    
    m_delegate = NULL;

    // We need to stop all its children here
    foreach(nr_device *child_device, m_child_device_list)
    {
        child_device->stop();
    }
    
    if (m_parent_device != NULL)
    {
        m_parent_device->on_child_stopped(this);
    }

    return NR_ERROR_NONE; 
}

nr_error_t nr_device::on_child_stopped(nr_device *chile_device) 
{ 
    // Check whether all its child are stopped
    bool is_all_child_stopped = true;
    for(QList<nr_device *>::iterator it = m_child_device_list.begin();
        it != m_child_device_list.end(); ++it)
    {
        nr_device *child_device = *it;
        if (child_device->status() != NR_DEVICE_STATUS_STOPPED)
        {
            is_all_child_stopped = false;
        }
    }
    
    // All child stopped and itself not used 
    if (!is_all_child_stopped && m_delegate == NULL)
    {
        stop();

        m_status = NR_DEVICE_STATUS_STOPPED;
    }

    return NR_ERROR_NONE;
}

nr_error_t nr_device::send_out_data(nr_data* data)
{
    // Do not send data if device not started
    if (m_status == NR_DEVICE_STATUS_STARTED)
    {
        if (m_delegate != NULL)
            m_delegate->on_data_received(data);
    }
        
    return NR_ERROR_NONE;
}

void nr_device::add_child_device(nr_device *child_device)
{
    child_device->parent_device() = this;
    m_child_device_list.push_back(child_device);
}

void nr_device::remove_child_device(nr_device *child_device)
{
    m_child_device_list.removeOne(child_device);
}
